﻿/*
Copyright © 2011 François Karman

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

See <license.txt> for the complete license of the software.
*/

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;

namespace Simple.Storage
{
    /// <summary>
    /// Defines the actions available on the data source to manipulates data.
    /// </summary>
    public interface IDataSource : IDisposable
    {
        /// <summary>
        /// Occurs before saving an object.
        /// </summary>
        event EventHandler<InstanceEventArgs> Saving;

        /// <summary>
        /// Occurs before loading an object.
        /// </summary>
        event EventHandler<KeyEventArgs> Loading;

        /// <summary>
        /// Occurs before deleting an object.
        /// </summary>
        event EventHandler<KeyEventArgs> Deleting;

        /// <summary>
        /// Occurs after saving an object.
        /// </summary>
        event EventHandler<InstanceEventArgs> Saved;

        /// <summary>
        /// Occurs after loading an object.
        /// </summary>
        event EventHandler<InstanceEventArgs> Loaded;

        /// <summary>
        /// Occurs after deleting an object.
        /// </summary>
        event EventHandler<KeyEventArgs> Deleted;

        /// <summary>
        /// Gets the unique name of the data source.
        /// </summary>
        /// <remarks>
        /// This name should be unique in the current application context to avoid
        /// data collisions and impredictable issues.
        /// </remarks>
        string Name { get; }

        /// <summary>
        /// Creates a new query to extract values for a specified persisted class.
        /// </summary>
        /// <typeparam name="T">The type of the persisted class.</typeparam>
        /// <returns>The query object.</returns>
        /// <exception cref="UnknownClassException">
        /// <typeparamref name="T"/> is not a persisted class.
        /// </exception>
        [SuppressMessage(
            "Microsoft.Design",
            "CA1006:DoNotNestGenericTypesInMemberSignatures",
            Justification = "Correspond to the IDataSource design")]
        IEnumerable<IDescriptor<T>> Query<T>();

        /// <summary>
        /// Loads a specified persisted instance.
        /// </summary>
        /// <typeparam name="T">The type of the retrieved instance.</typeparam>
        /// <param name="key">The key of the retrieved instance.</param>
        /// <returns>The retrieved instance.</returns>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="key"/> parameter is <c>null</c>.
        /// </exception>
        /// <exception cref="UnknownClassException">
        /// <typeparamref name="T"/> is not a persisted class.
        /// </exception>
        /// <exception cref="WrongKeyTypeException">
        /// The <paramref name="key"/> parameter is not of the expected type.
        /// </exception>
        /// <exception cref="KeyNotFoundException">
        /// There is no element associated with the specified <paramref name="key"/>.
        /// </exception>
        [SuppressMessage(
            "Microsoft.Design",
            "CA1004:GenericMethodsShouldProvideTypeParameter",
            Justification = "Correspond to the IDataSource design")]
        T Load<T>(object key);

        /// <summary>
        /// Persists a specified instance.
        /// </summary>
        /// <typeparam name="T">The type of the saved instance.</typeparam>
        /// <param name="instance">The instance to persist.</param>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="instance"/> parameter is <c>null</c>.
        /// </exception>
        /// <exception cref="UnknownClassException">
        /// <typeparamref name="T"/> is not a persisted class.
        /// </exception>
        void Save<T>(T instance);

        /// <summary>
        /// Deletes a specified instance.
        /// </summary>
        /// <typeparam name="T">The type of the deleted instance.</typeparam>
        /// <param name="key">The key of the deleted instance.</param>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="key"/> parameter is <c>null</c>.
        /// </exception>
        /// <exception cref="UnknownClassException">
        /// <typeparamref name="T"/> is not a persisted class.
        /// </exception>
        /// <exception cref="WrongKeyTypeException">
        /// The <paramref name="key"/> parameter is not of the expected type.
        /// </exception>
        /// <exception cref="KeyNotFoundException">
        /// There is no element associated with the specified <paramref name="key"/>.
        /// </exception>
        [SuppressMessage(
            "Microsoft.Design",
            "CA1004:GenericMethodsShouldProvideTypeParameter",
            Justification = "Correspond to the IDataSource design")]
        void Delete<T>(object key);

        /// <summary>
        /// Removes and cleans everything associated with the data source.
        /// As expected, this action is irreversible.
        /// </summary>
        void RemoveEverything();
    }
}
